/****************************************************
	文件：EnemyAI.cs
	作者：HuskyT
	邮箱：1005240602@qq.com
	日期：2020/5/31 20:1:37
	功能：敌人 AI
*****************************************************/
#define USE_RANDOM_WEIGHTED //使用随机权重

using System.Linq;
using System.Collections.Generic;
using UnityEngine;

namespace AIModule.Utility.Example
{
    public class EnemyAI : AIBase
    {
        public EnemyAI(EnemyEntity selfEntity)
        {
            mSelf = selfEntity;
            mCommandList = new List<CommandBase>();
        }

        /// <summary>
        /// 选择下一个命令
        /// </summary>
        public override CommandBase ChooseNextCommand()
        {
            UpdateCommandScore(); //更新各个命令的效用分数
#if USE_RANDOM_WEIGHTED
            int randomNum = MathUtil.GetRandom(1, 100);
            //Debug.Log("roll : " + randomNum);
            float topScore = 100.0f;
            float bottomScore = 100.0f;
            foreach (var command in mCommandList)
            {
                bottomScore -= command.Score;
                if (randomNum <= topScore && randomNum > bottomScore)
                {
                    return command;
                }
                topScore = bottomScore;
            }
            Debug.LogErrorFormat("{0} ChooseNextCommand Error !", mSelf.Model.Name);
            return null;
#else
            return mCommandList.OrderByDescending(command => command.Score).First();
#endif
        }
        /// <summary>
        /// 更新各个命令的效用分数
        /// </summary>
        private void UpdateCommandScore()
        {
            mCommandList.Clear();
            float threat = ThreatScore(mSelf.BB.OpponentModel.Entity);
            float attack = AttackScore(mSelf.BB.OpponentModel.Entity);
            float curative = UseCurativePotionScore() * threat;
            float run = RunawayScore() * threat * 0.5f;
            //Debug.LogFormat("threat:{0}--attack:{1}--curative:{2}--run:{3}", threat, attack, curative, run);
            float total = attack + curative + run;
            attack = 100.0f * attack / total;
            curative = 100.0f * curative / total;
            run = 100.0f * run / total;
            mCommandList.Add(new AttackCommand(new AttackBev()) { Score = attack, });
            mCommandList.Add(new UseCurativePotionCommand(new UseCurativePotionBev()) { Score = curative, });
            mCommandList.Add(new RunawayCommand(new RunawayBev()) { Score = run, });
            Debug.LogFormat("{0} 各行为的效用分数：\nAttack :                  {1}\nUseCurativePotion :  {2}\nRunaway :               {3}", mSelf.Model.Name, attack, curative, run);
        }
        /// <summary>
        /// 计算对手带来的威胁分数
        /// </summary>
        protected override float ThreatScore(EntityBase opponent)
        {
            int opponentMaxDmg = opponent.Model.Atk.Value + opponent.Model.AtkRangeRadius.Value - mSelf.Model.Def.Value;
            float score = Mathf.Min(1f * opponentMaxDmg / mSelf.Model.Hp.Value, 1f);
            return score;
        }
        /// <summary>
        /// 计算攻击的效用分数
        /// </summary>
        protected override float AttackScore(EntityBase opponent)
        {
            EnemyModel model = (EnemyModel)mSelf.Model;
            int maxDmg = model.Atk.Value + model.AtkRangeRadius.Value - opponent.Model.Def.Value;
            int minDmg = model.Atk.Value - model.AtkRangeRadius.Value - opponent.Model.Def.Value;
            float score = (1.0f - (opponent.Model.Hp.Value - minDmg) * 1.0f / (maxDmg - minDmg)) * (1.0f - model.DefaultAttackUtility) + model.DefaultAttackUtility;
            score = Mathf.Max(model.DefaultAttackUtility, Mathf.Min(1, score));
            return score;
        }
        /// <summary>
        /// 计算使用恢复药剂的效用分数
        /// </summary>
        protected override float UseCurativePotionScore()
        {
            if (mSelf.Model.CurativePotionNum.Value == 0
                || mSelf.Model.Hp.Value >= mSelf.Model.MaxHp.Value) return 0; //没有恢复药剂
            float power = -(12.0f * mSelf.Model.Hp.Value / mSelf.Model.MaxHp.Value) + 6.0f;
            float exponent = 1.0f + Mathf.Pow((Consts.EULER_NUMBER * 0.68f), power); //分母
            float score = 1.0f - (1.0f / exponent);
            return score;
        }
        /// <summary>
        /// 计算逃跑行为的效用分数
        /// </summary>
        protected override float RunawayScore()
        {
            float power = 0.25f * Mathf.Pow((mSelf.Model.CurativePotionNum.Value + 1), -4);
            float score = 1.0f - Mathf.Pow(1.0f * mSelf.Model.Hp.Value / mSelf.Model.MaxHp.Value, power);
            return score;
        }
    }
}